﻿namespace Ann
{
  using System;
  using System.Collections;
  using System.Collections.Generic;
  using System.Text;
  using Reals.Existence;
  using Reals.Parellel;

  /// <summary>
  /// AnnCell 人工神经元网络中的细胞，即神经元本身。
  /// </summary>
  public partial class AnnNeuron : AnnCell<AnnNeuron.AnnLinker>
  {
    #region Consts
    #region For exporters
    /// <summary>
    /// 每个输出端的囊泡数量（50万个）。
    /// </summary>
    public const uint DefaultVesiclesPerExporter = 500000;
    /// <summary>
    /// 每个囊泡包含递质的数量。
    /// 约为1000到50000个，这里
    /// 用12000个作为初始化量。
    /// </summary>
    public const uint DefaultTransmittersPerVesicle = 12000; //1000-50000
    /// <summary>
    /// 每个输出含有的递质数量。
    /// 约为6.0e9个。
    /// </summary>
    public const ulong DefaultTransmittersPerExporter 
      = (ulong) DefaultVesiclesPerExporter * (ulong) DefaultTransmittersPerVesicle;
    /// <summary>
    /// 一次神经冲动可以送出的囊泡的最少数量（依赖于电位）。
    /// （相当于50*12000个递质分子）
    /// </summary>
    public const uint DefaultMinVesiclesPerPulse = 50;
    /// <summary>
    /// 一次神经冲动可以送出的囊泡的最大数量（依赖于电位）。
    /// （相当于300*12000个递质分子）
    /// </summary>
    public const uint DefaultMaxVesiclesPerPulse = 300;
    #endregion
    #region For importers
    /// <summary>
    /// 每个输入端受体的数量（两千万个，2.0e+7）。
    /// </summary>
    public const uint DefaultReceptorsPerImporter = 20000000;

    /// <summary>
    /// 激活一个受体需要的递质数量（12000/2000＝6）。
    /// </summary>
    public const uint DefaultTransmittersPerReceptor = 6;
    #endregion
    #endregion
    #region Statics
    /// <summary>
    /// 获取到指定细胞的传感器。
    /// </summary>
    public static AnnSensor sensorOf(AnnNeuron neuron)
    {
      return AnnSensor.of(neuron);
    }
    public static AnnReader readerOf(AnnNeuron neuron)
    {
      return AnnReader.of(neuron);
    }
    /// <summary>
    /// 获取链接到指定输出端的执行器。
    /// </summary>
    public static AnnPerformer performerOf(AnnExporter exporter)
    {
      return AnnPerformer.of(exporter);
    }
    #endregion
    #region Inner Classes
    #region Importers/Exporters
    /// <summary>
    /// 细胞用于输入或者输出的连接。
    /// </summary>
    public abstract class AnnLinker : MicroExistentImpl
    {
      #region Statics
      #endregion
      #region Fields
      /// <summary>
      /// 当前管线的容器。
      /// </summary>
      protected AnnNeuron cell = null;
      #endregion
      #region Properties
      /// <summary>
      /// 获取容器细胞。
      /// </summary>
      public virtual AnnNeuron Cell
      {
        get
        {
          return this.cell;
        }
      }
      public virtual bool HasCell
      {
        get
        {
          return this.cell != null;
        }
      }
      #endregion
      #region Constructors
      public AnnLinker(AnnNeuron cell)
      {
        this.cell = cell;
      }
      #endregion
      #region Methods
      public override bool Attach(MicroCycling cycling)
      {
        if (base.Attach(cycling))
        {
          cycling.AddMicroProcess("InternalAction",new MicroProcess(this.InternalAction));
          //添加管线的时序。
          return true;
        }
        return false;
      }
      #region Internal Methods
      protected virtual bool InternalAction()
      {
        return true;
      }
      #endregion
      #endregion
    }
    /// <summary>
    /// Exporter
    /// </summary>
    /// <remarks>
    /// Ann输出端用于和目的Ann的连接和信号的发放。
    /// 它记录目的Ann，递质泡数，和递质泡的平均容量，
    /// 用以计算发放时的递质量。
    /// </remarks>
    public class AnnExporter : AnnLinker
    {
      #region Statics
      public static AnnExporter of(AnnNeuron cell)
      {
        return new AnnExporter(cell);
      }
      public static AnnExporter of(AnnNeuron cell, uint vesicles)
      {
        return new AnnExporter(cell, vesicles);
      }
      public static AnnExporter of(AnnNeuron cell, AnnImporter peerImporter, uint vesicles)
      {
        return new AnnExporter(cell, peerImporter, vesicles);
      }
      #endregion
      #region Fields
      /// <summary>
      /// 当前输出端的对应输入端。
      /// </summary>
      /// <remarks>
      /// 必须记录输入端以便进行递质的传输。
      /// </remarks>
      protected AnnImporter peerImporter = null;
      /// <summary>
      /// 当前输出端中含有囊泡的总量。
      /// </summary>
      protected uint vesicles = DefaultVesiclesPerExporter;
      /// <summary>
      /// 平均每个囊泡的递质含量。
      /// </summary>
      protected uint transmittersPerVesicle = DefaultTransmittersPerVesicle;
      #endregion
      #region Properties
      /// <summary>
      /// 获取对等输入。
      /// </summary>
      public virtual AnnImporter PeerImporter
      {
        get
        {
          return this.peerImporter;
        }
        set
        {
          this.peerImporter = value;
        }
      }
      /// <summary>
      /// 判别当前输出是否具有对等输入。
      /// </summary>
      public virtual bool HasPeerImporter
      {
        get
        {
          return this.peerImporter != null;
        }
      }
      /// <summary>
      /// 获取或者设置囊泡的数量。
      /// </summary>
      public virtual uint Vesicles
      {
        get
        {
          return this.vesicles;
        }
        set
        {
          this.vesicles = value;
        }
      }
      /// <summary>
      /// 获取或者设定每个囊泡含递质的数量（平均值）。
      /// </summary>
      public virtual uint TransmittersPerVesicle
      {
        get
        {
          return this.transmittersPerVesicle;
        }
        set
        {
          this.transmittersPerVesicle = value;
        }
      }
      #endregion
      #region Constructors
      public AnnExporter(AnnNeuron cell)
        : this(cell, DefaultVesiclesPerExporter)
      {
      }
      public AnnExporter(AnnNeuron cell, uint vesicles)
        : this(cell, null, vesicles)
      {
      }
      /// <summary>
      /// 输出端的构造方法。
      /// </summary>
      public AnnExporter(AnnNeuron cell, AnnImporter peerImporter, uint vesicles)
        : base(cell)
      {
        this.peerImporter = peerImporter;
        this.vesicles = vesicles;
      }
      #endregion
      #region Methods
      /// <summary>
      /// 将输出链接到输入端。
      /// </summary>
      public virtual AnnImporter AttachImporter(AnnImporter importer)
      {
        if (importer != null)
        {
          (this.peerImporter = importer).PeerExporter = this;
        }
        return importer;
      }
      /// <summary>
      /// 分离输入端。
      /// </summary>
      public virtual AnnImporter DetachImporter()
      {
        AnnImporter importer = this.PeerImporter;

        if (importer !=null)
        {
          AnnNeuron neuron =  importer.Cell;

          if (neuron != null)
          {
            neuron.RemoveImporter(importer);
          }

          importer.PeerExporter = null;
          this.PeerImporter = null;
        }
        return importer;
      }
      /// <summary>
      /// 产生脉冲。
      /// </summary>
      /// <param name="potential">给定电位。</param>
      public virtual ulong Pulse(double potential)
      {
        return this.Pulse(this.ReleaseVesicles(potential));
      }
      /// <summary>
      /// 产生脉冲。
      /// </summary>
      /// <remarks>
      /// 打开vesciles数量的囊泡，释放相应数量的
      /// 递质。
      /// </remarks>
      public virtual ulong Pulse(uint vesiclesCount)
      {
        ulong transmitters = 0L;

        if (this.HasPeerImporter)
        {
          transmitters = PeerImporter.CaptureTransmitters(
             Utils.Decrease(ref this.vesicles,vesiclesCount) * this.TransmittersPerVesicle
            );
        }

        return transmitters;
      }
      /// <summary>
      /// 根据电位计发出囊泡的数量。
      /// </summary>
      /// <remarks>
      /// 这个数量和钙离子流入的量有关，但在此可以简化
      /// </remarks>
      protected virtual uint ReleaseVesicles(double potential)
      {
        return 0;
      }
      #region Disposing
      protected override void Dispose(bool disposing)
      {
        if (disposing)
        {
          this.DetachImporter();
        }
        base.Dispose(disposing);
      }
      #endregion
      #endregion
    }
    /// <summary>
    /// Importer
    /// </summary>
    /// <remarks>
    /// Ann输入用于接受Exporter传入的递质。
    /// 递质在输入端代谢并推动输入端的蛋白质
    /// 门的开放，导致外部离子的流入。
    /// 
    /// Importer即受体所在的后膜。
    /// 在这里，受体的数量是可调的：若递质浓度较高，
    /// 则受体的数量会减少，否则受体的数量会增加。
    /// 所以，受体不是决定通透率长期稳定改变的根本
    /// 原因。
    /// </remarks>
    public class AnnImporter : AnnLinker
    {
      #region Statics
      public static AnnImporter of(AnnNeuron cell)
      {
        return new AnnImporter(cell);
      }
      public static AnnImporter of(AnnNeuron cell, uint receptors)
      {
        return new AnnImporter(cell, receptors);
      }
      public static AnnImporter of(AnnNeuron cell, AnnExporter peerExporter, uint receptors)
      {
        return new AnnImporter(cell, peerExporter, receptors);
      }
      #endregion
      #region Fields
      /// <summary>
      /// 当前输入端的对等输出端。
      /// </summary>
      protected AnnExporter peerExporter = null;
      /// <summary>
      /// 当前输入端的运送器（或者称为门）数量。
      /// </summary>
      protected uint receptors = DefaultReceptorsPerImporter;
      /// <summary>
      /// 已经打开的通道数量。
      /// </summary>
      protected uint openChannels = 0;
      /// <summary>
      /// 判别当前输入端是否正在接受脉冲。
      /// </summary>
      protected bool isPulsing = false;
      #endregion
      #region Properties
      /// <summary>
      /// 获取对等输出端。
      /// </summary>
      public virtual AnnExporter PeerExporter
      {
        get
        {
          return this.peerExporter;
        }
        set
        {
          this.peerExporter = value;
        }
      }
      public virtual bool HasPeerExporter
      {
        get
        {
          return this.peerExporter != null;
        }
      }
      /// <summary>
      /// 获取运送器数量。
      /// </summary>
      public virtual uint Receptors
      {
        get
        {
          return this.receptors;
        }
        set
        {
          this.receptors = value;
        }
      }
      /// <summary>
      /// 获取或者设置当前输入端打开通道的数量。
      /// </summary>
      public virtual uint OpenChannels
      {
        get
        {
          return this.openChannels;
        }
        set
        {
          this.openChannels = value;
        }
      }
      public virtual bool IsPulsing
      {
        get
        {
          return this.isPulsing;
        }
      }
      #endregion
      #region Constructors
      public AnnImporter(AnnNeuron cell)
        : this(cell, DefaultReceptorsPerImporter)
      {
      }
      public AnnImporter(AnnNeuron cell, uint receptors)
        : this(cell, null, receptors)
      {
      
      }
      public AnnImporter(AnnNeuron cell, AnnExporter peerExporter, uint receptors)
        : base(cell)
      {
        this.peerExporter = peerExporter;
        this.receptors = receptors;
      }
      #endregion
      #region Methods
      #region Publics
      public virtual AnnExporter AttachExporter(AnnExporter exporter)
      {
        if (exporter != null)
        {
          exporter.AttachImporter(this);
        }
        return exporter;
      }
      public virtual AnnExporter DetachExporter()
      {
        AnnExporter exporter = this.PeerExporter;

        if (exporter != null)
        {
          exporter.DetachImporter();
        }
        return exporter;
      }
      /// <summary>
      /// 捕获从输出端输出的递质信号。
      /// </summary>
      /// <param name="transmitters">捕获的递质数量。</param>
      public virtual ulong CaptureTransmitters(ulong transmitters)
      {
        this.isPulsing = true;

        if (this.HasCell)
        {
          //对于传入的递质，打开一定数量的通道。
          //受体的数量和通道的数量相等
          //记录打开通道的数量，当没有输入发生的时候，
          //关闭相等数量的通道。
          this.Cell.OpenChannels(openChannels = Utils.Decrease(ref this.receptors, (uint)(transmitters / DefaultTransmittersPerReceptor)));
        }
        return openChannels * DefaultTransmittersPerReceptor;
      }
      #endregion
      #region Internals
      protected virtual bool InternalActivity()
      {
        if (this.isPulsing)
        {
          this.isPulsing = false;
        }
        return true;
      }
      #endregion
      #region Disposing
      protected override void Dispose(bool disposing)
      {
        if (disposing)
        {
          this.DetachExporter();
        }
        base.Dispose(disposing);
      }
      #endregion
      #endregion
    }
    #endregion
    #region Extensions
    #region Sensor
    /// <summary>
    /// 神经传感器
    /// </summary>
    /// <remarks>
    /// 神经传感器模拟输出端的功能，
    /// 可以用于将外部数据直接输入
    /// 到细胞之中。
    /// </remarks>
    public class AnnSensor : AnnExporter
    {
      #region Statics
      public static new AnnSensor of(AnnNeuron neuron)
      {
        return new AnnSensor(neuron);
      }
      #endregion
      #region Constructors
      public AnnSensor(AnnNeuron neuron)
        : base(null)
      {
        this.AttachImporter(neuron);
      }
      #endregion
      #region Methods
      public override ulong Pulse(uint vesicles)
      {
        //需要线程同步，保证正确输入
        lock (this)
        {
          return base.Pulse(vesicles);
        }
      }
      /// <summary>
      /// 将输出端链接到神经元上的一个新输入端。
      /// </summary>
      public virtual AnnImporter AttachImporter(AnnNeuron neuron)
      {
        return neuron != null ? this.AttachImporter(neuron.GenerateImporter()) : null;
      }
      #endregion
    }

    /// <summary>
    /// 神经用于读入字符数据的阅读器。
    /// </summary>
    public class AnnReader:AnnSensor
    {
      #region Statics
      public static new AnnReader of(AnnNeuron neuron)
      {
        return new AnnReader(neuron);
      }
      #endregion
      #region Consts
      //字符数据使用的脉冲电位。
      public const double DefaultCharPotential = 20e-3;
      //字符数据启动的脉冲电位。
      public const double DefaultPrefixPotential = 40e-3;
      //字符的位数。
      public const uint CharBits = 16;
      //移位的次数。
      public const uint MaxShifts = CharBits - 1;

      #endregion
      #region Fields
      protected bool isReading = false;
      protected char readingChar = '\0';
      protected uint readingIndex = 0;
      protected double prefixPotential = DefaultPrefixPotential;
      protected double charPotential = DefaultCharPotential;
      #endregion
      #region Properties
      public virtual bool IsReading
      {
        get
        {
          return this.isReading;
        }
      }
      public virtual char ReadingChar
      {
        get
        {
          return this.readingChar;
        }
      }
      public virtual uint ReadingIndex
      {
        get
        {
          return this.readingIndex;
        }
      }
      public virtual double PrefixPotential
      {
        get
        {
          return this.prefixPotential;
        }
        set
        {
          this.prefixPotential = value;
        }
      }
      public virtual double CharPotential
      {
        get
        {
          return this.charPotential;
        }
        set
        {
          this.charPotential = value;
        }
      }
      #endregion
      #region Constructors
       public AnnReader(AnnNeuron neuron)
        : base(neuron)
      {
      }
      #endregion
      #region Methods
      public virtual bool Read(char readingChar)
      {
        lock (this)
        {
          if (!this.isReading)
          {
            this.readingChar = readingChar;

            return this.isReading = true;
          }
          return false;
        }
      }
      protected override bool InternalAction()
      {
        if (this.IsReading)
        {
          if (this.readingIndex < MaxShifts)
          {
            //必须先发出启动脉冲，以便识别。
            if (this.readingIndex++ == 0)
            {
              this.Pulse(this.prefixPotential);
            }
            else
            {
              int bit = (this.readingChar >> ((int)this.readingIndex + 1)) & 0x01;

              if (bit == 1)
              {
                this.Pulse(this.charPotential);
              }
              if (++this.readingIndex == MaxShifts)
              {
                this.readingIndex = 0;
                this.isReading = false;
              }
            }
          }
        }
        return base.InternalAction();
      }
      #endregion
    }
    #endregion
    #region Performer
    /// <summary>
    /// 神经执行器
    /// </summary>
    /// <remarks>
    /// 神经执行器模拟输入端的功能，
    /// 可以用于将神经信号直接发送到
    /// 其他非神经系统。
    /// </remarks>
    public class AnnPerformer : AnnImporter
    {
      #region Statics
      public static AnnPerformer of(AnnExporter exporter)
      {
        return new AnnPerformer(exporter);
      }
      #endregion
      #region Constructors
      public AnnPerformer(AnnExporter exporter)
        : base(null)
      {
        this.AttachExporter(exporter);
      }
      #endregion
      #region Methods
      #endregion
    }

    public class AnnWriter:AnnPerformer
    {
      #region Statics
      #endregion
      #region Consts
      //字符的位数。
      public const uint CharBits = 16;
      //移位的次数。
      public const uint MaxShifts = CharBits - 1;
      #endregion
      #region Fields
      protected bool isWriting = false;
      protected char writtingChar = '\0';
      protected uint writtingIndex = 0;
      #endregion
      #region Properties
      #endregion
      #region Constructors
       public AnnWriter(AnnExporter exporter)
        : base(exporter)
      {
      }
      #endregion
      #region Methods
      protected override bool InternalAction()
      {
        if (this.isPulsing)
        {

        }
        return base.InternalAction();
      }
      #endregion
    }
    #endregion
    #endregion
    #endregion
    #region Methods
    //public override AnnNeuron.AnnLinker Remove(AnnNeuron.AnnLinker microPart)
    //{
    //  if (microPart is AnnImporter && this.Importers.Contains(microPart as AnnImporter))
    //  {
    //    this.Importers.Remove(microPart as AnnImporter);
    //  }
    //  if (microPart is AnnExporter && this.Exporters.Contains(microPart as AnnExporter))
    //  {
    //    this.Exporters.Remove(microPart as AnnExporter);
    //  }
    //  return base.Remove(microPart);
    //}
    #endregion
  }
}
